<?php

declare (strict_types=1);

namespace wuwu\cosydevtool\command\addons;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;

class Build extends Command
{
    /**
     * 应用基础目录
     * @var string
     */
    protected $basePath;

    protected $buildLsit;

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('cosy:build')
            ->addArgument('title', Argument::OPTIONAL, 'app title .')
            ->addArgument('name', Argument::OPTIONAL, 'app data .')
            ->addArgument('description', Argument::OPTIONAL, 'app description .')
            ->addArgument('author', Argument::OPTIONAL, 'app author .')
            ->addArgument('version', Argument::OPTIONAL, 'app version .')
            ->setDescription('Create a new addons');
    }

    protected function execute(Input $input, Output $output)
    {
        $this->basePath = $this->getBasePath();
        $output->writeln($this->basePath);
        $app = $input->getArgument('name') ?: '';
        cache($app . '_date', date('YmdHis', time()), 60);
        if (is_file($this->basePath . 'build.php')) {
            $list = include $this->basePath . 'build.php';
        } else {
            $list = [
                '__dir__' => ['controller', 'model', 'view', 'database'],
            ];
        }
        $this->buildLsit = $list;
        $list['database'][0] = cache($app . '_date') . $list['database'][0];
        $this->buildApp($app, $list);
        $output->writeln("<info>Successed</info>");

    }

    /**
     * 获取应用基础目录
     * @access public
     * @return string
     */
    public function getBasePath(): string
    {
        return root_path() . 'addons' . DIRECTORY_SEPARATOR;
    }

    /**
     * 创建应用
     * @access protected
     * @param string $app 应用名
     * @param array $list 目录结构
     * @return void
     */
    protected function buildApp(string $app, array $list = []): void
    {
        if (!is_dir($this->basePath . $app)) {
            // 创建应用目录
            mkdir($this->basePath . $app);
        }

        $appPath = $this->basePath . ($app ? $app . DIRECTORY_SEPARATOR : '');
        $namespace = 'addons' . ($app ? '\\' . $app : '');

        // 创建配置文件和公共文件
        $this->buildCommon($app);

        foreach ($list['__dir__'] as $key => $val){
            if($key != 'database')
                $this->buildControllerHello($app, $val, $key, $namespace);
        }

        foreach ($list as $path => $file) {
            if ('__dir__' == $path) {
                // 生成子目录
                foreach ($file as $key => $dir) {
                    if (gettype($dir) == 'string') {
                        $this->checkDirBuild($appPath . $dir);
                    }
                    if (gettype($dir) == 'array') {
                        $this->checkArrayDirBuild($appPath . $key, $dir);
                    }
                }
            } elseif ('__file__' == $path) {
                // 生成（空白）文件
                foreach ($file as $name) {
                    if (!is_file($appPath . $name)) {
                        file_put_contents($appPath . $name, $this->buildFile($namespace, $app, explode('.', $name)[0]));
//                        file_put_contents($appPath . $name, 'php' == pathinfo($name, PATHINFO_EXTENSION) ? '<?php' . PHP_EOL : '');
                    }
                }
            } else {
                // 生成相关MVC文件
                foreach ($file as $val) {
                    $val = trim($val);
                    $filename = $appPath . $path . DIRECTORY_SEPARATOR . $val . '.php';
                    $space = $namespace . '\\' . $path;
                    $class = $val;
                    switch ($path) {
                        case 'controller': // 控制器
                            if ($this->app->config->get('route.controller_suffix')) {
                                $filename = $appPath . $path . DIRECTORY_SEPARATOR . $val . 'Controller.php';
                                $class = $val . 'Controller';
                            }
                            $content = "<?php" . PHP_EOL . "namespace {$space};" . PHP_EOL . PHP_EOL . "class {$class}" . PHP_EOL . "{" . PHP_EOL . PHP_EOL . "}";
                            break;
                        case 'model': // 模型
                            $content = "<?php" . PHP_EOL . "namespace {$space};" . PHP_EOL . PHP_EOL . "use think\Model;" . PHP_EOL . PHP_EOL . "class {$class} extends Model" . PHP_EOL . "{" . PHP_EOL . PHP_EOL . "}";
                            break;
                        case 'view': // 视图
                            $filename = $appPath . $path . DIRECTORY_SEPARATOR . $val . '.html';
                            $this->checkDirBuild(dirname($filename));
                            $content = '';
                            break;
                        case 'database': //数据
                            $content = "<?php" . PHP_EOL . PHP_EOL . "use addons\\" . $app . "\\Update;" . PHP_EOL . 'use think\migration\Migrator;' . PHP_EOL . PHP_EOL . "//此文件不可改动" . PHP_EOL . "class Upgrade extends Migrator" . PHP_EOL . "{" . PHP_EOL . '    use Update;' . PHP_EOL . "}";
                            break;

                        default:
                            // 其他文件
                            $content = "<?php" . PHP_EOL . "namespace {$space};" . PHP_EOL . PHP_EOL . "class {$class}" . PHP_EOL . "{" . PHP_EOL . PHP_EOL . "}";
                    }

                    if (!is_file($filename)) {
                        file_put_contents($filename, $content);
                    }
                }
            }
        }
    }

    /**
     * 创建应用的欢迎页面
     * @access protected
     * @param string $app 目录
     * @param string $namespace 类库命名空间
     * @return void
     */
    protected function buildControllerHello(string $app, array $module, string $moduleName, string $namespace): void
    {
        $suffix = $this->app->config->get('route.controller_suffix') ? 'Controller' : '';
        $filename = $this->basePath . ($app ? $app . DIRECTORY_SEPARATOR : '') . $moduleName . DIRECTORY_SEPARATOR . 'controller' . DIRECTORY_SEPARATOR . 'Index' . $suffix . '.php';

        if (!is_file($filename)) {
            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'controller.stub');
            $content = str_replace(['{%name%}', '{%app%}', '{%layer%}', '{%suffix%}'], [$app, $namespace . DIRECTORY_SEPARATOR . $moduleName, 'controller', $suffix], $content);
            $this->checkDirBuild(dirname($filename));

            file_put_contents($filename, $content);
        }

        if(count($module['controller']) > 0){
            $filename = $this->basePath . ($app ? $app . DIRECTORY_SEPARATOR : '') . $moduleName . DIRECTORY_SEPARATOR . 'controller' . DIRECTORY_SEPARATOR . 'v1' . DIRECTORY_SEPARATOR . 'Index' . $suffix . '.php';

            $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'controller.stub');
            $content = str_replace(['{%name%}', '{%app%}', '{%layer%}', '{%suffix%}'], ['v1' . DIRECTORY_SEPARATOR . $app, $namespace . DIRECTORY_SEPARATOR . $moduleName, 'controller' . DIRECTORY_SEPARATOR .'v1', $suffix], $content);
            $this->checkDirBuild(dirname($filename));

            file_put_contents($filename, $content);
        }
    }

    /**
     * 创建应用的公共文件
     * @access protected
     * @param string $app 目录
     * @return void
     */
    protected function buildCommon(string $app): void
    {
        $appPath = $this->basePath . ($app ? $app . DIRECTORY_SEPARATOR : '');

        if (!is_file($appPath . 'common.php')) {
            file_put_contents($appPath . 'common.php', "<?php" . PHP_EOL . "// 这是系统自动生成的公共文件" . PHP_EOL);
        }

        foreach (['event', 'middleware', 'common'] as $name) {
            if (!is_file($appPath . $name . '.php')) {
                file_put_contents($appPath . $name . '.php', "<?php" . PHP_EOL . "// 这是系统自动生成的{$name}定义文件" . PHP_EOL . "return [" . PHP_EOL . PHP_EOL . "];" . PHP_EOL);
            }
        }
    }

    /**
     * 创建目录
     * @access protected
     * @param string $dirname 目录名称
     * @return void
     */
    protected function checkDirBuild(string $dirname): void
    {
        if (!is_dir($dirname)) {
            mkdir($dirname, 0755, true);
        }
    }

    protected function checkArrayDirBuild($appPath, $array)
    {
        if (!is_dir($appPath)) {
            mkdir($appPath, 0755, true);
        }
        $appPath = $appPath . DIRECTORY_SEPARATOR;

        foreach ($array as $key => $dir) {
            if (gettype($dir) == 'string') {
                $this->checkDirBuild($appPath . $dir);
            }
            if (gettype($dir) == 'array') {
                $this->checkArrayDirBuild($appPath . $key, $dir);
            }
        }
    }

    protected function buildFile($namespace, $app, $name)
    {
        $file = __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . $name . '.stub';
        $stub = file_get_contents($file);

        if ($name == 'Plugin') {
            return str_replace([
                '{%namespace%}',
                '{%title%}',
                '{%name%}',
                '{%description%}',
                '{%author%}',
                '{%version%}',
                '{%date%}'
            ],
                [
                    $namespace,
                    $this->input->getArgument('title'),
                    $app,
                    $this->input->getArgument('description'),
                    $this->input->getArgument('author'),
                    $this->input->getArgument('version'),
                    cache($app . '_date')
                ], $stub);
        } else {
            return str_replace([
                '{%namespace%}',
                '{%name%}',
                '{%date%}'
            ],
                [
                    $namespace,
                    $app,
                    cache($app . '_date')
                ], $stub);
        }
    }
}
